﻿namespace MapleRock.P2PEmulator.Test.Experiments
{
  using System;
  using System.Collections.Generic;
  using System.Diagnostics;
  using System.IO;
  using System.Linq;
  using System.Text;

  using Core;
  using Core.Events;

  using NUnit.Framework;

  [TestFixture]
  public class RoutingExperiments
  {
    [SetUp]
    public void SetUp()
    {
      System.Diagnostics.DefaultTraceListener listener =
        (System.Diagnostics.DefaultTraceListener)
        System.Diagnostics.Trace.Listeners[0];
      listener.AssertUiEnabled = true;
    }

    [TestCase]
    public void DeliveryTimeByLength()
    {
      const string OutputFilePath = @"d:\out\experiments\delivery_time_by_length.tsv";

      var path = Path.GetDirectoryName(OutputFilePath);
      Directory.CreateDirectory(path);
      File.Delete(OutputFilePath);

      var lengthTimePairs = new List<KeyValuePair<double, double>>();

      for (var i = 0; i < 10; ++i)
      {
        var network = Utils.CreateNetwork(3, 1200, 1200, 10, 2, 8, 30, PeerBehaviour.DoesNothing);
        network.PrepareRun();

        for (uint firstIndex = 1; firstIndex <= network.State.Peers.Count; ++firstIndex)
        {
          for (uint secondIndex = 1; secondIndex <= network.State.Peers.Count; ++secondIndex)
          {
            if (firstIndex == secondIndex)
            {
              continue;
            }

            var firstPeer = network.State.Peers[firstIndex];
            var secondPeer = network.State.Peers[secondIndex];

            var message = new LocateServiceMessage(network.State.GenerateUniqueId());

            message.From = firstIndex;
            message.To = secondIndex;

            firstPeer.Outgoing.Enqueue(message);

            var startTick = network.State.TimePassedMs;

            while (secondPeer.Incoming.Count == 0)
            {
              network.Go(1);
            }

            secondPeer.Incoming.Clear();

            var endTick = network.State.TimePassedMs;

            var firstCity = network.State.Cities[firstPeer.CityId];
            var secondCity = network.State.Cities[secondPeer.CityId];

            if ((endTick - startTick) > 0)
            {
              lengthTimePairs.Add(new KeyValuePair<double, double>(
                firstCity.GetDistance(secondCity), endTick - startTick));
            }
          }
        }
      }

      var filteredLengthTimePairs = new List<KeyValuePair<double, double>>();
      foreach (var rawEntry in lengthTimePairs)
      {
        if (filteredLengthTimePairs.Any(
          entry => (entry.Key == rawEntry.Key)))
        {
          continue;
        }

        filteredLengthTimePairs.Add(rawEntry);
      }

      var output = File.OpenWrite(OutputFilePath);
      var writer = new StreamWriter(output);

      foreach (var pair in filteredLengthTimePairs)
      {
        writer.WriteLine("{0}\t{1}", pair.Key, pair.Value);
      }

      writer.Close();
      output.Close();
    }
  }
}
